import { Maths } from "../utils/Maths";

interface iPos {
    h: number,
    v: number
}

export default class MapTool {

    public basicMaps: number = 5;

    public hCount: number = 4;
    public vCount: number = 4;

    //上下左右
    public dir: iPos[] = [{ h: -1, v: 0 }, { h: 1, v: 0 }, { h: 0, v: -1 }, { h: 0, v: 1 }];

    public tagArr: Array<Array<number>> = [];

    public mapArr: Array<Array<string>> = [];

    public findQuene: number[] = [];

    public createMap(): Array<Array<string>> {

        for (let i = 0; i < this.hCount; i++) {
            this.tagArr[i] = [];
            for (let j = 0; j < this.vCount; j++) {
                this.tagArr[i][j] = 0;
            }
        }

        let start: iPos =
        {
            h: Math.floor(Math.random() * this.hCount),
            v: Math.floor(Math.random() * this.vCount),
        };

        this.findQuene.push(Maths.Arr2To1(start.h, start.v, this.vCount));

        this.getNearBlocks(start, 0);

        while (this.basicMaps > 0 && this.findQuene.length > 0) {

            let randomIndex = Math.floor(Math.random() * this.findQuene.length);

            let vec2 = Maths.Arr1To2(this.findQuene[randomIndex], this.vCount);

            let next = { h: vec2.x, v: vec2.y };

            this.getNearBlocks(next, randomIndex);
        }

        for (let i = 0; i < this.hCount; i++) {
            this.mapArr[i] = [];
            for (let j = 0; j < this.vCount; j++) {
                this.mapArr[i][j] = "00000";
            }
        }

        for (let i = 0; i < this.hCount; i++) {
            for (let j = 0; j < this.vCount; j++) {
                this.checkConnect(i, j);
            }
        }
        console.log(this.mapArr);

        return this.mapArr;
    }

    public checkConnect(h: number, v: number): void {
        if (this.mapArr[h][v] == "00000" && this.tagArr[h][v] != 1) {
            return;
        }

        for (let i = 0; i < this.dir.length; i++) {
            let nearPos = {
                h: this.dir[i].h + h,
                v: this.dir[i].v + v,
            }

            if (!this.checkItHas(nearPos)) {
                continue;
            }

            if (this.tagArr[nearPos.h][nearPos.v] == 1) {

                this.mapArr[h][v] = this.changeName(this.mapArr[h][v], i);

                let index = 0;;
                if (nearPos.h > h) {// near 在下 开口向上
                    index = 0;
                } else if (nearPos.h < h) { // near 在上 开口向下
                    index = 1;
                } else if (nearPos.v > v) { // near 在右 开口向左
                    index = 2;
                } else if (nearPos.v < v) { //near 在左 开口向右
                    index = 3;
                }
                this.mapArr[nearPos.h][nearPos.v] = this.changeName(this.mapArr[nearPos.h][nearPos.v], index);
            }

        }
    }

    public changeName(str: string, index: number, value: string = "1"): string {
        let arr = str.split("");

        arr.splice(index, 1, value);

        return arr.join("");
    }

    public getNearBlocks(pos: iPos, index: number): void {
        if (!pos)
            return;

        if (this.tagArr[pos.h][pos.v] == 1) {
            console.log("isthis");
            return;
        }

        this.tagArr[pos.h][pos.v] = 1;

        this.findQuene.splice(index, 1);

        this.basicMaps--;

        for (let i = 0; i < this.dir.length; i++) {
            let nearPos = {
                h: this.dir[i].h + pos.h,
                v: this.dir[i].v + pos.v
            }

            if (!this.checkItHas(nearPos)) {
                continue;
            }

            if (this.tagArr[nearPos.h][nearPos.v] == 1) {
                continue;
            }

            let value = Maths.Arr2To1(nearPos.h, nearPos.v, this.vCount)

            if (this.findQuene.indexOf(value) != -1) {
                continue
            }

            this.findQuene.push(value);
        }
    }

    public checkItHas(pos: iPos): boolean {
        if (pos.h < 0 || pos.v < 0 || pos.h >= this.hCount || pos.v >= this.vCount) {
            return false;
        } else {
            return true;
        }
    }
}
